<script setup lang="ts">
import { type Ref, ref } from 'vue'
import { Add } from '@vicons/ionicons5'
import { type UploadFileInfo, type FormRules } from 'naive-ui'
import { imageUrlToFile } from '@/hooks/imageUrlToFile'
import { userGetUserDetailService, userAddUserService, userUpdateUserService } from '@/api/user'

// 是否显示抽屉
const show: Ref<boolean> = ref(false)
//消息提示框
const message = useMessage()

// 表单数据
type FormModel = {
  id: number | null
  username: string
  password: string
  nickname: string
  email: string
  gender: number
  avatar: File | null
  desc: string
  isAdmin: boolean
  [key: string]: any
}
// 是否为编辑状态
const isEdit: Ref<boolean> = ref(false)

//预览图片地址
const imgUrl = ref('')

//表单数据
const formModel: Ref<FormModel> = ref({
  id: null,
  username: '',
  password: '',
  nickname: '',
  email: '',
  gender: 0,
  avatar: null,
  desc: '',
  isAdmin: false
})
//默认表单数据
const defaultFormModel: FormModel = {
  id: null,
  username: '',
  password: '',
  nickname: '',
  email: '',
  gender: 0,
  avatar: null,
  desc: '',
  isAdmin: false
}
// 打开抽屉
const open = async (id?: number) => {
  if (id) {
    isEdit.value = true
    const res = await userGetUserDetailService(id)
    // 预览图片地址
    imgUrl.value = res.data.data.avatar
    // 通过网络图片地址转换为File对象
    const avatar = await imageUrlToFile('res.data.data.avatar', 'avatar.jpg')
    // 编辑采用接口返回的数据
    formModel.value = {
      id: res.data.data.id,
      username: res.data.data.username,
      password: res.data.data.password,
      nickname: res.data.data.nickname,
      email: res.data.data.email,
      gender: res.data.data.gender,
      avatar: avatar,
      desc: res.data.data.desc,
      isAdmin: res.data.data.isAdmin
    }
  } else {
    isEdit.value = false
    //新增采用默认表单数据
    formModel.value = {
      ...defaultFormModel
    }
    // 清空图片预览
    imgUrl.value = ''
  }
  show.value = true
}

// 上传前的钩子函数限制只能上传一张图片
const fileList: Ref<Array<File>> = ref([])
const beforeUpload = (file: File) => {
  console.log(1)
  fileList.value = [] // 清空 fileList
  fileList.value.push(file)
  return true
}
// 上传图片预览
const handleImgChange = (fileList: UploadFileInfo[]) => {
  console.log(fileList)
  const file = fileList[0].file as File
  //更新表单数据,表单数据并没有upload绑定，所以这里需要手动更新
  formModel.value.avatar = file
  imgUrl.value = URL.createObjectURL(file)
}

//校验规则
const formRef = ref()
const rules: FormRules = {
  username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    { min: 6, message: '密码长度至少6位', trigger: 'blur' }
  ],
  nickname: [{ required: true, message: '请输入昵称', trigger: 'blur' }],
  email: [
    { required: true, message: '请输入邮箱', trigger: 'blur' },
    { type: 'email', message: '请输入正确的邮箱', trigger: 'blur' }
  ],
  gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
  desc: [],
  isAdmin: [{ required: true, message: '请选择权限', trigger: 'change' }]
}

//提交数据
//数据更新
const emit = defineEmits<{
  updateData: [operate: string]
}>()
const onSubmit = async (e: MouseEvent) => {
  e.preventDefault()
  //校验表单
  await formRef.value.validate()
  if (!formModel.value.id) {
    // 新增，id为null视为新增，id让后端自动生成
    const formData = new FormData()
    for (let key in formModel.value) {
      // id不需要传递
      if (key === 'id') continue
      formData.append(key, formModel.value[key])
    }
    message.success('新增成功')
    show.value = false
    //清空表单数据
    formModel.value = {
      ...defaultFormModel
    }
    const res = await userAddUserService(formData)
    // 通知更新数据
    emit('updateData', 'add')
    console.log(res.data.data)
    console.log(...formData.entries())
  } else {
    // 编辑
    const formData = new FormData()
    for (let key in formModel.value) {
      formData.append(key, formModel.value[key])
    }
    message.success('编辑成功')
    show.value = false
    //清空表单数据
    formModel.value = {
      ...defaultFormModel
    }
    const res = await userUpdateUserService(formData)
    // 通知更新数据
    emit('updateData', 'edit')
    console.log(res.data.data)
    console.log(...formData.entries())
  }
}
// 暴露给父组件的属性和方法
defineExpose({
  open
})
</script>

<template>
  <n-drawer v-model:show="show" :width="480">
    <n-drawer-content :title="formModel.id !== 0 ? '编辑用户' : '新增用户'" :native-scrollbar="false" closable>
      <n-form :rules="rules" :model="formModel" ref="formRef">
        <n-form-item label="用户名" path="username">
          <n-input v-model:value="formModel.username" placeholder="请输入用户名" :disabled="isEdit" />
        </n-form-item>
        <n-form-item label="密码" path="password">
          <n-input v-model:value="formModel.password" placeholder="请输入密码" />
        </n-form-item>
        <n-form-item label="昵称" path="nickname">
          <n-input v-model:value="formModel.nickname" placeholder="请输入昵称" />
        </n-form-item>
        <n-form-item label="邮箱" path="email">
          <n-input v-model:value="formModel.email" placeholder="请输入邮箱" />
        </n-form-item>
        <n-form-item label="性别">
          <n-radio-group v-model:value="formModel.gender">
            <n-space>
              <n-radio :value="0">男</n-radio>
              <n-radio :value="1">女</n-radio>
            </n-space>
          </n-radio-group>
        </n-form-item>
        <n-form-item label="头像">
          <n-upload
            list-type="image-card"
            :default-upload="false"
            :file-list="fileList"
            :before-upload="beforeUpload"
            :show-preview-button="false"
            :multiple="false"
            :on-update:file-list="handleImgChange"
            class="relative rounded-2"
          >
            <img v-if="imgUrl" :src="imgUrl" class="w-full h-full rounded" alt="哈哈" />
            <n-icon v-show="!imgUrl" :component="Add" class="absolute"></n-icon>
          </n-upload>
        </n-form-item>
        <n-form-item label="描述">
          <n-input v-model:value="formModel.desc" placeholder="请输入描述" />
        </n-form-item>
        <n-form-item label="权限">
          <n-radio-group v-model:value="formModel.isAdmin">
            <n-space>
              <n-radio :value="true">管理人员</n-radio>
              <n-radio :value="false">普通用户</n-radio>
            </n-space>
          </n-radio-group>
        </n-form-item>
        <n-form-item>
          <n-button type="info" class="rounded-2" @click="onSubmit">提交</n-button>
        </n-form-item>
      </n-form>
    </n-drawer-content>
  </n-drawer>
</template>

<style scoped></style>
